/*
 * Created on 2005-3-16
 */
package com.hd123.rumba.request;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.Vector;

import org.apache.log4j.Logger;

import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.user.IUser;
import com.hd123.rumba.util.StringUtil;

/**
 * @author caili
 */
/**
 * @author caili
 */
/**
 * @author caili
 */
/**
 * @author caili
 */
public class ActionAcl {
  private static Logger logger = Logger.getLogger(ActionAcl.class);
  private static ActionAcl instance = null;
  private HashMap acl; // key=action, value=Vector of permissions

  public HashMap getAcl() {
    return acl;
  }

  public static ActionAcl getInstance() {
    if (instance == null) {
      instance = new ActionAcl();
    }
    return instance;
  }

  private ActionAcl() {
    super();
    acl = new HashMap();
    try {
      loadAcl();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 从资源中构建acl
   * 
   * @throws Exception
   */
  private void loadAcl() throws Exception {

    ResourceBundle props = ResourceBundle.getBundle("actionAcl");
    Enumeration keys = props.getKeys();
    while (keys.hasMoreElements()) {
      String key = (String) keys.nextElement();
      String value = props.getString(key);
      StringTokenizer st = new StringTokenizer(value, ";");
      Vector v = new Vector();
      while (st.hasMoreElements()) {
        String perm = (String) st.nextElement();
        v.add(new String(perm.getBytes("ISO-8859-1")));
      }
      acl.put(key, v);
    }
  }

  public Vector getAcl(String action) {
    Vector perms = new Vector();
    StringTokenizer st = new StringTokenizer(action, ".");
    String[] ar = new String[st.countTokens()];
    for (int i = 0; st.hasMoreTokens(); ar[i++] = st.nextToken())
      ;
    for (int i = ar.length - 1; i >= 0; --i) {
      String s = ar[0];
      for (int k = 1; k <= i; ++k) {
        s = s + "." + ar[k];
      }
      logger.debug(">>" + s);
      if (acl.containsKey(s)) {
        perms.addAll((Vector) acl.get(s));
        break;
      }
    }
    logger.debug(">>" + perms);
    return perms;
  }

  /**
   * 如果用户没有登录(user==null), 则只能执行标明为ignore的动作
   * 如果用户登录了, 可执行没有标明权限的(没有定义权限)动作, 标明了ignore的动作, 用户具有标明了的权限之一
   * @param user
   * @param action
   * @return
   */
  public boolean hasAcl(IUser user, String action) throws BusinessException{
    Vector permissions = (Vector) getAcl(action);
    if (user == null) {
      return permissions.contains("ignore");
    }
    if (permissions.size() == 0)
      return true;
    if (permissions.contains("ignore"))
      return true;
    Vector userPerms = user.getPermissionIds();
    if (userPerms == null)
      return false;
    permissions.retainAll(userPerms);
    return permissions.size() > 0;
  }

  public static void main(String[] args) {
    HashMap acl = ActionAcl.getInstance().getAcl();
    logger.debug(StringUtil.printAll(acl, " ", "\n"));

    logger.debug("--------user.ViewUser.save-------");
    logger.debug(ActionAcl.getInstance().getAcl("user.ViewUser.save"));
    logger.debug("--------user.ViewRole-------");
    logger.debug(ActionAcl.getInstance().getAcl("user.ViewRole"));
    logger.debug("--------user.ViewRole.save-------");
    logger.debug(ActionAcl.getInstance().getAcl("user.ViewRole.save"));
    logger.debug("--------user.ViewRole.save.do-------");
    logger.debug(ActionAcl.getInstance().getAcl("user.ViewRole.save.do"));
    logger.debug("--------auser.ViewRole.save.do-------");
    logger.debug(ActionAcl.getInstance().getAcl("auser.ViewRole.save.do"));
    logger.debug("--------user-------");
    logger.debug(ActionAcl.getInstance().getAcl("user"));

    logger.debug("--------getAcl(user.ViewRole.save.do)-------");
    Vector userPerms = new Vector();
    userPerms.add("user");
    userPerms.add("role");
    Vector perms = ActionAcl.getInstance().getAcl("user.ViewRole.save.do");
    logger.debug(perms);
    logger.debug(userPerms);
    perms.retainAll(userPerms);
    logger.debug(perms);
  }

}
